[HVM] Fix assumptions that ISA IRQ 0 connects to GSI 0.
authorkaf24@localhost.localdomain <kaf24@localhost.localdomain>
Thu, 28 Dec 2006 16:33:15 +0000 (16:33 +0000)
committerkaf24@localhost.localdomain <kaf24@localhost.localdomain>
Thu, 28 Dec 2006 16:33:15 +0000 (16:33 +0000)
Signed-off-by: Keir Fraser <keir@xensource.com>
xen/arch/x86/hvm/irq.c
xen/arch/x86/hvm/vioapic.c
xen/arch/x86/hvm/vpt.c
xen/include/asm-x86/hvm/irq.h

index e9f975eb534179b419f55ef11ea5a810b0dc9dd7..1b51f5905c0ec73d1e38880144a3f913073afd42 100644 (file)
@@ -85,7 +85,7 @@ void hvm_isa_irq_assert(
     struct domain *d, unsigned int isa_irq)
 {
     struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
-    unsigned int gsi = (isa_irq == 0) ? 2 : isa_irq;
+    unsigned int gsi = hvm_isa_irq_to_gsi(isa_irq);
 
     ASSERT(isa_irq <= 15);
 
@@ -105,7 +105,7 @@ void hvm_isa_irq_deassert(
     struct domain *d, unsigned int isa_irq)
 {
     struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
-    unsigned int gsi = (isa_irq == 0) ? 2 : isa_irq;
+    unsigned int gsi = hvm_isa_irq_to_gsi(isa_irq);
 
     ASSERT(isa_irq <= 15);
 
@@ -257,23 +257,25 @@ int cpu_get_interrupt(struct vcpu *v, int *type)
     return -1;
 }
 
-int get_intr_vector(struct vcpu* v, int irq, int type)
+int get_isa_irq_vector(struct vcpu *v, int isa_irq, int type)
 {
+    unsigned int gsi = hvm_isa_irq_to_gsi(isa_irq);
+
     if ( type == APIC_DM_EXTINT )
-        return v->domain->arch.hvm_domain.irq.vpic[irq >> 3].irq_base
-                + (irq & 0x7);
+        return (v->domain->arch.hvm_domain.irq.vpic[isa_irq >> 3].irq_base
+                + (isa_irq & 7));
 
-    return domain_vioapic(v->domain)->redirtbl[irq].fields.vector;
+    return domain_vioapic(v->domain)->redirtbl[gsi].fields.vector;
 }
 
-int is_irq_masked(struct vcpu *v, int irq)
+int is_isa_irq_masked(struct vcpu *v, int isa_irq)
 {
-    if ( is_lvtt(v, irq) )
-        return !is_lvtt_enabled(v);
+    unsigned int gsi = hvm_isa_irq_to_gsi(isa_irq);
 
-    if ( v->domain->arch.hvm_domain.irq.vpic[irq >> 3].imr & (1 << (irq & 7))
-            && domain_vioapic(v->domain)->redirtbl[irq].fields.mask )
-        return 1;
+    if ( is_lvtt(v, isa_irq) )
+        return !is_lvtt_enabled(v);
 
-    return 0;
+    return ((v->domain->arch.hvm_domain.irq.vpic[isa_irq >> 3].imr &
+             (1 << (isa_irq & 7))) &&
+            domain_vioapic(v->domain)->redirtbl[gsi].fields.mask);
 }
index f986d5ca1da35b2e6eef91427555e680445e0bcc..843c76a6ddc314a1ade265e43911349ea8f6d653 100644 (file)
@@ -341,7 +341,7 @@ static void vioapic_deliver(struct vioapic *vioapic, int irq)
     {
 #ifdef IRQ0_SPECIAL_ROUTING
         /* Force round-robin to pick VCPU 0 */
-        if ( irq == 0 )
+        if ( irq == hvm_isa_irq_to_gsi(0) )
         {
             v = vioapic_domain(vioapic)->vcpu[0];
             target = v ? vcpu_vlapic(v) : NULL;
@@ -374,7 +374,7 @@ static void vioapic_deliver(struct vioapic *vioapic, int irq)
             deliver_bitmask &= ~(1 << bit);
 #ifdef IRQ0_SPECIAL_ROUTING
             /* Do not deliver timer interrupts to VCPU != 0 */
-            if ( (irq == 0) && (bit != 0) )
+            if ( irq == hvm_isa_irq_to_gsi(0) )
                 v = vioapic_domain(vioapic)->vcpu[0];
             else
 #endif
index cb320bb897ddf0186939aea5d0f1fcb16c36dc0e..12e8999582ddfa7201680e6dcd95b3559c3d4740 100644 (file)
@@ -108,16 +108,18 @@ void pt_update_irq(struct vcpu *v)
     list_for_each( list, head )
     {
         pt = list_entry(list, struct periodic_time, list);
-        if ( !is_irq_masked(v, pt->irq) && pt->pending_intr_nr 
-                && pt->last_plt_gtime + pt->period < max_lag )
+        if ( !is_isa_irq_masked(v, pt->irq) && pt->pending_intr_nr &&
+             ((pt->last_plt_gtime + pt->period_cycles) < max_lag) )
         {
-            max_lag = pt->last_plt_gtime + pt->period;
+            max_lag = pt->last_plt_gtime + pt->period_cycles;
             irq = pt->irq;
         }
     }
 
     if ( is_lvtt(v, irq) )
+    {
         vlapic_set_irq(vcpu_vlapic(v), irq, 0);
+    }
     else if ( irq >= 0 )
     {
         hvm_isa_irq_deassert(v->domain, irq);
@@ -141,16 +143,15 @@ struct periodic_time *is_pt_irq(struct vcpu *v, int vector, int type)
 
         if ( is_lvtt(v, pt->irq) )
         {
-            if (pt->irq == vector)
-                return pt;
-            else
+            if ( pt->irq != vector )
                 continue;
+            return pt;
         }
 
-        vec = get_intr_vector(v, pt->irq, type);
+        vec = get_isa_irq_vector(v, pt->irq, type);
 
         /* RTC irq need special care */
-        if ( vector != vec || (pt->irq == 8 && !is_rtc_periodic_irq(rtc)) )
+        if ( (vector != vec) || (pt->irq == 8 && !is_rtc_periodic_irq(rtc)) )
             continue;
 
         return pt;
@@ -163,14 +164,14 @@ void pt_intr_post(struct vcpu *v, int vector, int type)
 {
     struct periodic_time *pt = is_pt_irq(v, vector, type);
 
-    if (pt == NULL)
+    if ( pt == NULL )
         return;
 
     pt->pending_intr_nr--;
     pt->last_plt_gtime += pt->period_cycles;
     hvm_set_guest_time(pt->vcpu, pt->last_plt_gtime);
 
-    if (pt->cb)
+    if ( pt->cb != NULL )
         pt->cb(pt->vcpu, pt->priv);
 }
 
@@ -200,9 +201,11 @@ void create_periodic_time(struct periodic_time *pt, uint64_t period,
     destroy_periodic_time(pt);
 
     pt->enabled = 1;
-    if (period < 900000) /* < 0.9 ms */
+    if ( period < 900000 ) /* < 0.9 ms */
     {
-        printk("HVM_PlatformTime: program too small period %"PRIu64"\n", period);
+        gdprintk(XENLOG_WARNING,
+                 "HVM_PlatformTime: program too small period %"PRIu64"\n",
+                 period);
         period = 900000; /* force to 0.9ms */
     }
     pt->period = period;
index 85e3d3fa88c6a53cca54cd0533b40e5328c2f7c7..af66d67f2c12843f955574d775e7d0e7dc80c7f0 100644 (file)
@@ -61,7 +61,8 @@ struct hvm_irq {
     /*
      * Number of wires asserting each GSI.
      * 
-     * GSIs 0-15 are the ISA IRQs. ISA devices map directly into this space.
+     * GSIs 0-15 are the ISA IRQs. ISA devices map directly into this space
+     * except ISA IRQ 0, which is connected to GSI 2.
      * PCI links map into this space via the PCI-ISA bridge.
      * 
      * GSIs 16+ are used only be PCI devices. The mapping from PCI device to
@@ -87,6 +88,8 @@ struct hvm_irq {
 #define hvm_pci_intx_link(dev, intx) \
     (((dev) + (intx)) & 3)
 
+#define hvm_isa_irq_to_gsi(isa_irq) ((isa_irq) ? : 2)
+
 /* Modify state of a PCI INTx wire. */
 void hvm_pci_intx_assert(
     struct domain *d, unsigned int device, unsigned int intx);
@@ -106,7 +109,7 @@ void hvm_set_callback_gsi(struct domain *d, unsigned int gsi);
 
 int cpu_get_interrupt(struct vcpu *v, int *type);
 int cpu_has_pending_irq(struct vcpu *v);
-int get_intr_vector(struct vcpu* vcpu, int irq, int type);
-int is_irq_masked(struct vcpu *v, int irq);
+int get_isa_irq_vector(struct vcpu *vcpu, int irq, int type);
+int is_isa_irq_masked(struct vcpu *v, int isa_irq);
 
 #endif /* __ASM_X86_HVM_IRQ_H__ */